/*
 * @Author: xuetao 3168581151@qq.com
 * @Date: 2025-02-06
 * @LastEditors: xuetao 3168581151@qq.com
 * @LastEditTime: 2025-03-16
 * @Description: 
 */

import 'package:chat_client/config/api_config.dart';
import 'package:chat_client/config/socket_config.dart'
    show ConfirmEvents, MessageEvents, messageToMap;
import 'package:chat_client/enums/chat_enum.dart';
import 'package:chat_client/models/conversation_model.dart';
import 'package:chat_client/models/session_model.dart' show SessionModel;
import 'package:chat_client/providers/conversation_provider.dart';
import 'package:chat_client/repositories/conversation_repository.dart';
import 'package:chat_client/services/api_service.dart';
import 'package:chat_client/services/contact_service.dart';
import 'package:chat_client/services/group_service.dart';
import 'package:chat_client/services/socket/socket_service.dart';
import 'package:chat_client/utils/notify/notify_enum.dart'
    show NotificationType;
import 'package:chat_client/utils/notify/notify_helper.dart';
import 'package:chat_client/utils/route_tools.dart' show generatePath;
import 'package:chat_client/router/router.dart' show navigatorKey;
import 'package:provider/provider.dart';

class ConversationService {
  // 单例模式
  ConversationService._internal();
  static final ConversationService _instance = ConversationService._internal();
  static ConversationService get instance => _instance;

  final ApiService apiService = ApiService.instance;
  final SocketService _socket = SocketService.instance;
  final ConversationRepository _chatRepository =
      ConversationRepository.instance;
  final ContactService _contactService = ContactService.instance;
  final GroupService _groupService = GroupService.instance;

  Function(Message message) _messageListUpdate = (message) {};

  String currentChatSession = '';

  register() {
    messageReceipt();
    receivedMessage();
  }

  setCurrentChatSession(String chatSessionId) {
    currentChatSession = chatSessionId;
  }

  removeCurrentChatSession() {
    currentChatSession = '';
  }

  /// 刷新信息列表，当用户正在和某个好友聊天时，需要要更新内存中的messagesList
  addListenerMessageList(Function(Message message) updateMessages) {
    _messageListUpdate = updateMessages;
  }

  /// 移除刷新内存消息列表的监听器
  removeListenerMessageList() {
    _messageListUpdate = (message) {};
  }

  // 1. 发送信息
  Future sendMessage(Message message, SessionModel session) async {
    _socket.emitEvent(
        eventName: MessageEvents.messageSend,
        data: messageToMap(message: message, session: session));
  }

  // 2. 发送信息的回执监听器, 也就是本地化用户自己发出的消息
  messageReceipt() {
    storeReceipt(data) {
      final message = Message.fromJson(data);
      storeMessage(message); //储存消息
      // 储存消息，刷新会话列表
      _refreshConversationList();

      // 通知服务器确认我已收到消息并处理完毕
      _socket.emitEvent(
          eventName: ConfirmEvents.message,
          data: {'messageId': message.messageId});
    }

    _socket.addEventListener(MessageEvents.messageReceipt, storeReceipt);
  }

  // 3. 接收信息监听器
  receivedMessage() {
    // 消息接收
    storeReceived(data) async {
      final message = Message.fromJson(data);
      // 执行内存中的消息列表刷新逻辑
      _messageListUpdate(message);

      await storeMessage(message); //储存消息

      // 通知
      _notify(message);

      // 储存消息，刷新会话列表
      _refreshConversationList();

      // 通知服务器确认我已收到消息并处理完毕
      _socket.emitEvent(
          eventName: ConfirmEvents.message,
          data: {'messageId': message.messageId});
    }

    _socket.addEventListener(MessageEvents.messageReceive, storeReceived);
  }

  // 我方用户储存消息到本地
  Future storeMessage(Message message) async {
    // 会话不存在则拉取新会话
    if (message.conversationId == null) {
      throw WsError(message: 'conversationId 不存在');
    }
    Conversation? conversation =
        _chatRepository.getConversation(message.conversationId!);
    if (conversation == null) {
      // 拉取单个会话，包括消息
      await getConversationInfo(message.conversationId!);
    } else {
      // 往本地会话添加消息
      await _chatRepository.setConversation(conversation.addMessage(message));
      // 储存消息到本地
      await _chatRepository.setMessage(message);
    }
  }

  // HTTP

  /// 拉取单个会话
  Future getConversationInfo(String conversationId,
      {bool? offonline = false}) async {
    final response = await apiService.post('/conversation/info', {
      'conversationId': conversationId,
      'UNDELIVERED': offonline,
    });

    // 1. 本地化会话
    final con = response['data']['conversation'];
    final isPrivate =
        con['type'] == ConversationType.user.value && con['pivateId'] != null;
    final isGroup =
        con['type'] == ConversationType.group.value && con['groupId'] != null;
    if (isPrivate && isGroup || !isPrivate && !isGroup) {
      throw ApiError(message: '会话类型错误');
    }

    // 1.1 单聊会话
    if (isPrivate) {
      final contact = await _contactService.getContactSafe(con['pivateId']);
      if (contact == null) throw WsError(message: '非好友不能会话');
      con['avatarUrl'] = contact.avatarUrl;
      con['nickname'] = contact.remark;
    }
    // 1.2群聊会话
    else {
      final group = await _groupService.getGroupSafe(con['groupId']);
      if (group == null) throw WsError(message: '不在该群聊不能会话');
      con['avatarUrl'] = group.groupAvatar;
      con['nickname'] = group.groupName;
    }

    final conversation = Conversation.fromJson(con);
    await _chatRepository.setConversation(conversation);

    // 修改联系人和群聊信息
    if (isPrivate) {
      await _contactService.updateCoversationId(
        conversation.conversationId,
        conversation.pivateId!,
      );
    } else {
      await _groupService.updateCoversationId(
          conversationId, conversation.groupId!);
    }

    // 2.本地化消息
    final msList = response['data']['messageList'];

    for (var m in msList) {
      await storeMessage(Message.fromJson(m));
    }

    // 储存消息，刷新会话列表
    _refreshConversationList();
  }

  /// 获取远程会话列表和消息，并本地化
  Future<void> getRemoteConversationList({bool? offonline}) async {
    final response = await apiService.get('/conversation/all-conId');
    final conList = response['data'] as List;
    for (var conversationId in conList) {
      await getConversationInfo(conversationId['_id'], offonline: offonline);
    }
  }

  // 获取本地会话列表
  List<Conversation> getLocalConversationList() {
    return _chatRepository.getConversationList();
  }

  // 获取本地会话列表
  getLocalConvist() {
    return _chatRepository.getConversationList();
  }

  /// 其它

  /// 注意：需要判断是否显示通知

  // 弹窗通知
  _notify(Message message) {
    Conversation? con =
        _chatRepository.getConversation(message.conversationId!);

    if (message.conversationId == currentChatSession || con == null) return;

    final isPrivate = con.type == ConversationType.user.value;

    final type =
        isPrivate ? ConversationType.user.label : ConversationType.group.label;

    if (isPrivate && con.pivateId == currentChatSession ||
        !isPrivate && con.groupId == currentChatSession) {
      return;
    }

    // 弹窗通知
    NotifyHelper.notify(
      title: message.senderNickname ?? '新消息',
      content: message.data,
      type: NotificationType.chat,
      iconUrl: AppConfig.baseUrl + message.senderAvatar!,
      targetRoute: generatePath(
        type: type,
        id: message.senderId!,
      ),
    );
  }

  /// 刷新会话消息申请列表
  void _refreshConversationList() {
    final context = navigatorKey.currentContext;
    if (context != null) {
      context.read<ConversationProvider>().refreshConversationList();
    }
  }
}
